package com.ktjiaoyu.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktjiaoyu.server.mapper.AdminRoleMapper;
import com.ktjiaoyu.server.mapper.MenuMapper;
import com.ktjiaoyu.server.mapper.MenuRoleMapper;
import com.ktjiaoyu.server.mapper.RoleMapper;
import com.ktjiaoyu.server.pojo.AdminRole;
import com.ktjiaoyu.server.pojo.Menu;
import com.ktjiaoyu.server.pojo.MenuRole;
import com.ktjiaoyu.server.pojo.Role;
import com.ktjiaoyu.server.service.IAdminRoleService;
import com.ktjiaoyu.server.service.IMenuRoleService;
import com.ktjiaoyu.server.service.IRoleService;
import com.ktjiaoyu.server.vo.AdminRoleVo;
import com.ktjiaoyu.server.vo.RoleMenuVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jjx
 * @since 2024-01-23
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
    @Resource
    RoleMapper roleMapper;
    @Resource
    IAdminRoleService adminRoleService;
    @Resource
    AdminRoleMapper adminRoleMapper;
    @Resource
    MenuRoleMapper menuRoleMapper;
    @Resource
    IMenuRoleService menuRoleService;


    @Override
    public List<Role> roleList() {
        return roleMapper.selectList(null);
    }

    @Override
    public void batchInsertAdminRole(AdminRoleVo vo) {
        //1.先删除
        adminRoleService.remove(new QueryWrapper<AdminRole>().
                eq("adminId", vo.getAdminId()));
        //2.后新增
        List<AdminRole> saveAdminRole=new ArrayList<>();
        for (Integer rid : vo.getRid()) {
            AdminRole adminRole=new AdminRole();
            adminRole.setAdminId(vo.getAdminId());
            adminRole.setRid(rid);

            saveAdminRole.add(adminRole);
        }
        adminRoleService.saveBatch(saveAdminRole);
    }

    @Override
    public AdminRoleVo getAdminRoleList(Integer adminId) {
        QueryWrapper<AdminRole> wrapper = new QueryWrapper<AdminRole>();
        wrapper.eq("adminId", adminId);
        List<AdminRole> arList = adminRoleMapper.selectList(wrapper);
        // 如果当前用户没有被分配一个角色权限，那么就返回空的AdminRoleVo对象
        if (arList == null || arList.size() == 0) {
            return new AdminRoleVo();
        }
        List<Integer> ids = new ArrayList<Integer>();
        for (AdminRole ar : arList) {
            ids.add(ar.getRid());
        }
        AdminRoleVo vo = new AdminRoleVo(adminId, ids.toArray(new Integer[ids.size()]));
        return vo;

    }

    @Override
    public IPage<Role> selectByPage(Page<Role> page, String query, String sort) {
        //组装过滤条件
        QueryWrapper<Role> qw=new QueryWrapper<>();
        if (StringUtils.isNotEmpty(query)) {
            qw.like("name", query).or().like("nameZh", query);
        }
        //排序
//        if(sort.equals("+id")){
//            qw.orderByAsc("id");
//        }else{
//            qw.orderByDesc("id");
//        }

        //调用分页查询方法
        Page<Role> rolePage = roleMapper.selectPage(page, qw);


        // 获取到角色列表
        List<Role> roleList = rolePage.getRecords();

        // 遍历所有的角色列表信息
        roleList = roleList.stream().map((role) -> {
            // 遍历所有的角色列表，查询每个角色下的权限列表(这个权限列表需要进行一级、二级、三级分类)
            role.setChildren(getRightListByRole(role));
            return role;
        }).collect(Collectors.toList());

        //返回分页数据
        return rolePage;
    }

    // 查询当前角色所授权的所有权限
    private List<Menu> getRightListByRole(Role role) {
        // 查询当前角色下的权限列表集合
        List<Menu> menuList = roleMapper.findMenuByRole(role.getId());
        List<Menu> menus = null;
        if (menuList != null && menuList.size() > 0) {
            menus = menuList.stream().filter((menu) -> {
                // 过滤出当前角色下的一级权限列表，之后再调用map对这个一级权限列表进行遍历
                return menu.getParentId() != null && menu.getParentId() == 1;
            }).map((oneLevelMenu) -> { // 调用map对这个一级权限列表进行遍历
                // 遍历一级权限得到一级权限下的二级权限。
                oneLevelMenu.setChildren(getChildrens(oneLevelMenu, menuList));
                return oneLevelMenu;
            }).collect(Collectors.toList());
        } else {
            return null;
        }
        return menus;
    }

    /**
     * 得到当前权限下的子权限集合
     * @param oneLevelMenu 权限对象(比如一级或二级)
     * @param menuList 为当前角色所拥有的所有权限集合
     * @return 返回当前权限下的子权限列表
     */
    private List<Menu> getChildrens(Menu oneLevelMenu, List<Menu> menuList) {
        List<Menu> childMenuList = menuList.stream().filter((menu) ->
                // 过滤条件是：权限集合中menu对象的pid父级ID == 当前权限对象oneLevelMenu的ID
                // 实现将当前权限对象oneLevelMenu的子权限列表过滤出来，如果onLevelMenu为一级权限，
                // 那么就可以把这个一级权限下的二级权限给过滤出来。
                oneLevelMenu.getId().equals(menu.getParentId())
        ).map((sonMenu) -> {
            // 调用map方法，将过滤出来的子权限查询进行遍历。
            sonMenu.setChildren(getChildrens(sonMenu, menuList));
            return sonMenu;
        }).collect(Collectors.toList());
        return childMenuList;
    }

    // 保存角色信息
    @Override
    public boolean saveRole(Role role) {
        return roleMapper.insert(role) > 0 ? true : false;
    }

    // 保存修改后的角色信息
    @Override
    public boolean updateRole(Role role) {
        return roleMapper.updateById(role) > 0 ? true : false;
    }
    // 通过角色ID删除角色信息
    @Override
    public boolean delRoleById(Integer roleId) {
        try {
            // 1、通过角色ID到t_admin_role用户与角色中间表中删除相关信息
            adminRoleMapper.delete(new QueryWrapper<AdminRole>().eq("rid", roleId));
            // 2、通过角色ID到t_menu_role权限与角色中间表中删除相关信息
            menuRoleMapper.delete(new QueryWrapper<MenuRole>().eq("rid", roleId));
            // 3、再通过角色ID到t_role角色表中删除此角色信息
            roleMapper.deleteById(roleId);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void batchInsertRoleMenu(RoleMenuVo vo) {
        //1.先删除
        menuRoleService.remove(new QueryWrapper<MenuRole>().
                eq("rid", vo.getRid()));
        //2.后新增
        List<MenuRole> saveMenuRole=new ArrayList<>();
        for (Integer mid : vo.getMid()) {
            MenuRole menuRole=new MenuRole();
            menuRole.setRid(vo.getRid());
            menuRole.setMid(mid);

            saveMenuRole.add(menuRole);
        }
        menuRoleService.saveBatch(saveMenuRole);
    }


    // 根据角色ID删除对应的权限,将当前角色最新的权限列表进行返回
    @Override
    public List<Menu> delMenuByRoleId(Integer roleId, Integer menuId) {
        // 查询menu权限对象的所有子权限，并将这些子权限的id追加到List集合中
        List<Integer> sonMenuIds = getSonMenuIds(roleId, menuId);
        Integer[] menuIds = null; //多个子权限id使用逗号进行拼接
        if (sonMenuIds != null && sonMenuIds.size() > 0) {
            // 将List<Integer>转换成Integer[]数组
            menuIds = sonMenuIds.toArray(new Integer[sonMenuIds.size()]);
        }

        // 1、根据角色ID删除对应的权限(从t_menu_role表)
        QueryWrapper<MenuRole> wrapper = new QueryWrapper<MenuRole>();
        wrapper.eq("rid", roleId);
        if (menuIds == null || menuIds.length == 0) {
            // 说明本次删除是删除角色下的三级权限
            wrapper.eq("mid", menuId);
        } else {
            // 说明本次删除是删除角色下的一级或二级权限
            // DELETE FROM `t_menu_role` WHERE rid = 1 AND `mid` IN (10, 46)
            wrapper.in("mid", menuIds);
        }

        // delete from t_menu_role where mid = ? and rid = ?
        menuRoleMapper.delete(wrapper);
        // 2、将当前角色最新的权限列表查询出来，再进行返回
        Role role = new Role();
        role.setId(roleId);
        List<Menu> menus = getRightListByRole(role);
        return menus;
    }
    @Resource
    MenuMapper menuMapper;
    // 查询menu权限对象的所有子权限，并将这些子权限的id追加到List集合中
    private List<Integer> getSonMenuIds(Integer roleId, Integer menuId) {
        List<Integer> menuIds = new ArrayList<Integer>();
        // 通过即将要删除的权限id查询其详情对象信息
        Menu delMenu = menuMapper.selectById(menuId);
        if (3 != delMenu.getMenuLevel()) {
            // 判断要删除的菜单的等级是否为3，即三级权限，如果不是三级权限，那么在删除比如二级权限时，后面还需要将二级权限下的子权限一起从t_menu_role表中删除
            Role role = new Role();
            role.setId(roleId);
            // 获取当前角色下的所有权限
            List<Menu> menus = getRightListByRole(role);
            // 判断即将要删除的权限其权限等级是1还是2
            if (delMenu.getMenuLevel() == 1) {
                // 一级权限
                for (Menu currMenu : menus) {
                    if (currMenu.getId() == delMenu.getId()) {
                        menuIds.add(currMenu.getId());
                        // 遍历一级下的二级权限
                        for (Menu sonMenu : currMenu.getChildren()) {
                            menuIds.add(sonMenu.getId());
                            // 遍历二级下的三级权限
                            for (Menu threeMenu : sonMenu.getChildren()) {
                                menuIds.add(threeMenu.getId());
                            }
                        }
                        return menuIds;
                    }
                }
            } else {
                // 二级权限
                for (Menu currMenu : menus) {
                    // 遍历二级权限
                    for (Menu twoMenu : currMenu.getChildren()) {
                        if (twoMenu.getId() == delMenu.getId()) {
                            menuIds.add(twoMenu.getId());
                            // 遍历二级下的三级权限
                            for (Menu threeMenu : twoMenu.getChildren()) {
                                menuIds.add(threeMenu.getId());
                            }
                            return menuIds;
                        }
                    }
                }
            }
            return null;
        } else {
            return null;
        }
    }

}
